package com.zmn.plat.business.impl.price;

import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.plat.business.interfaces.pilot.ChannelPriceBService;
import com.zmn.plat.business.interfaces.price.AdvanceFlowBService;
import com.zmn.plat.business.interfaces.price.CommonBService;
import com.zmn.plat.business.interfaces.product.ServProductBService;
import com.zmn.plat.business.interfaces.servcategory.ShowCategoryAssociationBService;
import com.zmn.plat.common.constant.OnePriceConsts;
import com.zmn.plat.common.constant.ProductConsts;
import com.zmn.plat.common.dto.category.AssCategoryDRO;
import com.zmn.plat.common.dto.price.ItemTo;
import com.zmn.plat.common.dto.price.advance.AdvanceFtProductCheckTariffQuery;
import com.zmn.plat.common.dto.price.advance.AdvanceFtProductQuery;
import com.zmn.plat.common.dto.price.advance.AdvanceProductItemQuery;
import com.zmn.plat.common.dto.price.advance.AdvanceProductQuery;
import com.zmn.plat.common.dto.product.base.ProductBaseDRO;
import com.zmn.plat.common.dto.product.tariff.TariffBackProductDRO;
import com.zmn.plat.common.enums.PilotConfigEnum;
import com.zmn.plat.manager.dictionary.ProductDict;
import com.zmn.plat.model.dto.product.ProductRelationDTO;
import com.zmn.plat.model.entity.category.BaseCategory;
import com.zmn.plat.model.entity.category.BaseCategoryQuery;
import com.zmn.plat.model.entity.product.ServProduct;
import com.zmn.plat.model.entity.product.ServProductQuery;
import com.zmn.plat.model.entity.product.tariff.item.ProductItemQuery;
import com.zmn.plat.model.entity.product.tariff.item.ProductTariffGroupItemQuery;
import com.zmn.plat.model.entity.servcategory.ServCategory;
import com.zmn.plat.model.entity.servcategory.ShowCategoryAssociationVO;
import com.zmn.plat.services.interfaces.category.BaseCategoryService;
import com.zmn.plat.services.interfaces.product.ServProductService;
import com.zmn.plat.services.interfaces.product.tariff.ProductTariffService;
import com.zmn.plat.services.interfaces.product.tariff.item.ProductTariffGroupItemService;
import com.zmn.plat.services.interfaces.product.tariff.item.city.price.ProductTariffItemCityPriceService;
import com.zmn.plat.services.interfaces.servcategory.ServCategoryService;
import com.zmn.plat.services.interfaces.service.group.ServiceGroupService;
import com.zmn.plat.services.interfaces.service.tariff.ServiceTariffService;
import com.zmn.plat.utils.bean.BeanCopyUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 描述: 提前付流程实现类（所有接口前提是有计价器试点和预计价试点，专为提前付项目使用，接口是按照前台操作顺序来的）
 *
 * @author guoqiao
 * @since 2021/8/13 16:39
 */
@Service
@Slf4j
public class AdvanceFlowBServiceImpl implements AdvanceFlowBService {

    @Resource
    CommonBService commonBService;
    @Resource
    ProductTariffService productTariffService;
    @Resource
    ServiceTariffService serviceTariffService;
    @Resource
    ProductTariffGroupItemService productTariffGroupItemService;
    @Resource
    ProductTariffItemCityPriceService productTariffItemCityPriceService;
    @Resource
    ServiceGroupService serviceGroupService;
    @Resource
    ChannelPriceBService channelPriceBService;
    @Resource
    ServCategoryService servCategoryService;
    @Resource
    BaseCategoryService baseCategoryService;
    @Resource
    ServProductService servProductService;
    @Resource
    ServProductBService servProductBService;
    @Resource
    ShowCategoryAssociationBService showCategoryAssociationBService;

    @Override
    @Cacheable(cacheNames = "redis5m", key = "'price:listShowProduct:AdvanceFtProductQuery:'+#p0", unless = "#result == null")
    public List<ProductBaseDRO> listShowProduct(AdvanceFtProductQuery query) {

        // 查询前台产品
        ServProductQuery productQuery = new ServProductQuery();
        productQuery.setServCategId(query.getServCategId());
        productQuery.setCategId(query.getCategTwoId());
        productQuery.setBizType(query.getBizType());
        productQuery.setDefaultType(GlobalConsts.NO);
        productQuery.setStatus(GlobalConsts.YES);
        List<ServProduct> servProductList = servProductService.listByQuery(productQuery);
        if (CollectionUtils.isEmpty(servProductList)) {
            return null;
        }

        List<Integer> productIdList = servProductList.stream().map(e -> e.getProductId()).collect(Collectors.toList());
        // 查询前台、后台、计价器产品关系
        List<ProductRelationDTO> relationDTOList = Optional.ofNullable
                (servProductBService.listProductRalationByIdListAndShowType(productIdList, ProductConsts.EC_PRODUCT_TYPE))
                .orElse(Collections.emptyList())
                .stream()
                .filter(e -> Objects.equals(e.getTariffStatus(), GlobalConsts.YES)
                        && Objects.equals(e.getTariffProductStatus(), GlobalConsts.YES))
                .collect(Collectors.toList());

        // 查询价格表
        commonBService.getTariffByPilot(relationDTOList, query.getChannelId(), query.getCityId(), query.getBizType());
        log.info("计算后的产品关系价格表relationDTOList：{}", relationDTOList);

        List<ProductBaseDRO> droList = new ArrayList<>();

        // 筛选出价格表优先的数据
        commonBService.filterTariff(relationDTOList, ProductConsts.EC_PRODUCT_TYPE, true);
        List<Integer> productIdListDro = Optional.ofNullable(relationDTOList)
                .orElse(Collections.emptyList())
                .stream()
                .map(e -> e.getShowProductId())
                .collect(Collectors.toList());
        log.info("筛选出价格表优先的数据relationDTOFilterList：{}", productIdListDro);

        droList = servProductList
                .stream()
                .filter(m -> productIdListDro.contains(m.getProductId()))
                .map(m -> {
                    ProductBaseDRO dro = new ProductBaseDRO();
                    BeanCopyUtils.copyProperties(m, dro);
                    return dro;
                }).collect(Collectors.toList());
        return droList;
    }

    @Override
    @Cacheable(cacheNames = "redis5m", key = "'price:listItemByQuery:AdvanceProductItemQuery:'+#p0", unless = "#result == null")
    public List<ItemTo> listItemByQuery(AdvanceProductItemQuery query) {

        // 查询前台、后台、计价器产品关系
        List<ProductRelationDTO> relationDTOList = Optional.ofNullable
                (servProductBService.listProductRalationByIdListAndShowType(Arrays.asList(query.getShowProductId()), ProductConsts.EC_PRODUCT_TYPE))
                .orElse(Collections.emptyList())
                .stream()
                .filter(e -> Objects.equals(e.getTariffStatus(), GlobalConsts.YES)
                        && Objects.equals(e.getTariffProductStatus(), GlobalConsts.YES))
                .collect(Collectors.toList());

        // 查询价格表
        commonBService.getTariffByPilot(relationDTOList, query.getChannelId(), query.getCityId(), query.getBizType());
        log.info("计算后的产品关系价格表relationDTOList：{}", relationDTOList);

        // 筛选出价格表优先的数据
        commonBService.filterTariff(relationDTOList, ProductConsts.EC_PRODUCT_TYPE, true);
        log.info("筛选出价格表优先的数据relationDTOFilterList：{}", relationDTOList);

        List<Integer> itemIds = new ArrayList<>();
        // 查询项目
        List<ItemTo> result = new ArrayList<>();

        for (ProductRelationDTO relationDTO : relationDTOList) {
            ProductItemQuery itemQuery = new ProductItemQuery();
            itemQuery.setProductId(relationDTO.getProductId());
            itemQuery.setTariffId(relationDTO.getTariffId());
            itemQuery.setItemCategId(query.getItemCategId());

            List<ItemTo> itemTos = Optional.ofNullable(productTariffGroupItemService.listItemPriceByQuery(itemQuery))
                    .orElse(Collections.emptyList());

            for (ItemTo itemTo : itemTos) {
                if (!itemIds.contains(itemTo.getItemId())) {
                    itemIds.add(itemTo.getItemId());
                    result.add(itemTo);
                }
            }
        }
        return result;
    }

    @Override
    @Cacheable(cacheNames = "redis5m", key = "'price:listCategTwoByQuery:AdvanceProductQuery:'+#p0", unless = "#result == null")
    public List<AssCategoryDRO> listCategTwoByQuery(AdvanceProductQuery query) {

        // 查询所有服务分类
        Map<Integer, List<ServCategory>> servMap = Optional.ofNullable(servCategoryService.listServCategoryAll())
                .orElse(Collections.emptyList())
                .stream()
                .collect(Collectors.groupingBy(ServCategory::getCategId));

        // 查询有效的后台产品分类
        BaseCategoryQuery categoryQuery = new BaseCategoryQuery();
        categoryQuery.setStatus(GlobalConsts.YES);
        categoryQuery.setShowType(ProductConsts.ERP_PRODUCT_TYPE);
        Map<Integer, List<BaseCategory>> categoryMap = Optional.ofNullable(
                baseCategoryService.listByQuery(categoryQuery))
                .orElse(Collections.emptyList())
                .stream()
                .collect(Collectors.groupingBy(BaseCategory::getCategId));

        // 查询前台、后台、计价器产品关系
        List<ProductRelationDTO> relationDTOList = Optional.ofNullable
                (servProductBService.listProductRalationByIdListAndShowType(Arrays.asList(query.getShowProductId()), ProductConsts.EC_PRODUCT_TYPE))
                .orElse(Collections.emptyList())
                .stream()
                .filter(e -> Objects.equals(e.getTariffStatus(), GlobalConsts.YES)
                        && Objects.equals(e.getTariffProductStatus(), GlobalConsts.YES))
                .collect(Collectors.toList());

        // 查询价格表
        commonBService.getTariffByPilot(relationDTOList, query.getChannelId(), query.getCityId(), query.getBizType());
        log.info("计算后的产品关系价格表relationDTOList：{}", relationDTOList);

        // 筛选出价格表优先的数据
        commonBService.filterTariff(relationDTOList, ProductConsts.EC_PRODUCT_TYPE, true);
        log.info("筛选出价格表优先的数据relationDTOFilterList：{}", relationDTOList);

        List<AssCategoryDRO> dros = new ArrayList<>(relationDTOList.size());
        List<String> categs = new ArrayList<>();

        for (ProductRelationDTO relationDTO : relationDTOList) {
            Integer productId = relationDTO.getProductId();
            ProductTariffGroupItemQuery itemQuery = new ProductTariffGroupItemQuery();
            itemQuery.setProductId(productId);
            itemQuery.setTariffId(relationDTO.getTariffId());
            itemQuery.setItemIds(query.getItemList());
            // 能查询到结果，说明该产品满足要求
            int cunt = productTariffGroupItemService.countByQuery(itemQuery);
            if (cunt > 0) {
                ServProduct product = servProductService.findByKeyWithCache(productId);
                // 防止数据重复
                if (!categs.contains(product.getServCategId() + "-" + product.getCategId())) {
                    categs.add(product.getServCategId() + "-" + product.getCategId());
                    AssCategoryDRO dro = new AssCategoryDRO();
                    dro.setServCategId(product.getServCategId());
                    dro.setServCategName(servMap.get(dro.getServCategId()).get(0).getTariffName());
                    dro.setCategOneId(product.getCategOneId());
                    dro.setCategOneName(categoryMap.get(dro.getCategOneId()).get(0).getTariffName());
                    dro.setCategId(product.getCategId());
                    dro.setCategName(categoryMap.get(dro.getCategId()).get(0).getTariffName());
                    dros.add(dro);
                }
            }
        }
        return dros;
    }

    @Override
    @Cacheable(cacheNames = "redis5m", key = "'price:listProductByQuery:AdvanceProductQuery:'+#p0", unless = "#result == null")
    public List<TariffBackProductDRO> listProductByQuery(AdvanceProductQuery query) {

        // 查询前台、后台、计价器产品关系
        List<ProductRelationDTO> relationDTOList = Optional.ofNullable
                (servProductBService.listProductRalationByIdListAndShowType(Arrays.asList(query.getShowProductId()), ProductConsts.EC_PRODUCT_TYPE))
                .orElse(Collections.emptyList())
                .stream()
                .filter(e -> Objects.equals(e.getTariffStatus(), GlobalConsts.YES)
                        && Objects.equals(e.getTariffProductStatus(), GlobalConsts.YES))
                .collect(Collectors.toList());

        // 查询价格表
        commonBService.getTariffByPilot(relationDTOList, query.getChannelId(), query.getCityId(), query.getBizType());
        log.info("计算后的产品关系价格表relationDTOList：{}", relationDTOList);

        // 筛选出价格表优先的数据
        commonBService.filterTariff(relationDTOList, ProductConsts.EC_PRODUCT_TYPE, true);
        log.info("筛选出价格表优先的数据relationDTOFilterList：{}", relationDTOList);

        List<TariffBackProductDRO> dros = new ArrayList<>(relationDTOList.size());

        for (ProductRelationDTO relationDTO : relationDTOList) {
            Integer productId = relationDTO.getProductId();
            ProductTariffGroupItemQuery itemQuery = new ProductTariffGroupItemQuery();
            itemQuery.setProductId(productId);
            itemQuery.setTariffId(relationDTO.getTariffId());
            itemQuery.setItemIds(query.getItemList());
            // 能查询到结果，说明该产品满足要求
            int cunt = productTariffGroupItemService.countByQuery(itemQuery);
            if (cunt > 0) {
                ServProduct product = servProductService.findByKeyWithCache(productId);
                // 重构时替换成listByQuery
                if (Objects.nonNull(product) && Objects.equals(query.getServCategId(), product.getServCategId()) &&
                        Objects.equals(query.getCategTwoId(), product.getCategId()) && product.getBizType().contains(String.valueOf(query.getBizType()))) {
                    TariffBackProductDRO dro = new TariffBackProductDRO();
                    BeanCopyUtils.copyProperties(product, dro);
                    dro.setProductName(product.getName());
                    dro.setProductTariffName(product.getTariffName());
                    dro.setProductSort(product.getSort());
                    dros.add(dro);
                }
            }
        }
        return dros;
    }

//    @Override
//    @Cacheable(cacheNames = "redis5m", key = "'price:listItemPriceByQuery:AdvanceProductItemPriceQuery:'+#p0", unless = "#result == null")
//    public List<ItemTo> listItemPriceByQuery(AdvanceProductItemPriceQuery query) {
//
//        Integer bizType = query.getBizType();
//        Integer channelId = query.getChannelId();
//        Integer cityId = query.getCityId();
//
//        List<ItemTo> dros = new ArrayList<>();
//        Map<Integer, Integer> itemIdProductIdmap = new HashMap();
//
//        for (ProductItem productItem : query.getProductItemList()) {
//            // 查询后台产品
//            Integer productId = productItem.getProductId();
//            ServProduct product = servProductService.findByKeyWithCache(productId);
//
//            List<Integer> itemList = productItem.getItemList();
//            for (Integer itemid : itemList) {
//                itemIdProductIdmap.put(itemid, productId);
//            }
//
//            // 查询前台、后台、计价器产品关系
//            List<ProductRelationDTO> relationDTOList = Optional.ofNullable
//                    (servProductBService.listProductRalationByIdListAndShowType(Arrays.asList(productId), ProductConsts.ERP_PRODUCT_TYPE))
//                    .orElse(Collections.emptyList())
//                    .stream()
//                    .filter(e -> Objects.equals(e.getTariffStatus(), GlobalConsts.YES)
//                            && Objects.equals(e.getTariffProductStatus(), GlobalConsts.YES))
//                    .collect(Collectors.toList());
//            if (CollectionUtils.isEmpty(relationDTOList)) {
//                log.error("产品id:{},没有关联的可用数据", productId);
//                continue;
//            }
//
//            // 根据渠道城市查询产品的价格表id和类型
//            commonBService.getTariffByPilot(relationDTOList, channelId, cityId, bizType);
//            log.info("计算后的产品关系价格表relationDTOList：{}", relationDTOList);
//
//            if (Objects.isNull(relationDTOList.get(0).getTariffType()) || Objects.equals(ProductDict.TRIFF_TYPE_SERVICE, relationDTOList.get(0).getTariffType())) {
//                log.error("产品id:{},没有可用提前付价格表或计价器价格表", productId);
//                continue;
//            }
//
//            // 查询价格表
//            Integer tariffId = relationDTOList.get(0).getTariffId();
//            ServiceTariff tariff = serviceTariffService.findByKey(tariffId);
//
//            // 查询后台产品与价格表关系
//            ProductTariffQuery productTariffQuery = new ProductTariffQuery();
//            productTariffQuery.setProductId(productId);
//            productTariffQuery.setTariffId(tariffId);
//            productTariffQuery.setStatus(GlobalConsts.YES);
//            ProductTariffVO productTariffVO = Optional.ofNullable(productTariffService.listByQuery(productTariffQuery))
//                    .orElse(Collections.emptyList())
//                    .stream()
//                    .findFirst()
//                    .orElse(new ProductTariffVO());
//
//            // 查询item集合
//            List<ItemTo> itemToList = new ArrayList<>(itemList.size());
//            ProductItemQuery itemQuery = new ProductItemQuery();
//            itemQuery.setItemIds(itemList);
//            itemQuery.setProductId(productId);
//            itemQuery.setTariffId(tariffId);
//            if (Objects.equals(tariff.getPriceType(), ProductDict.TRIFF_PRICE_TYPE_CITY)) {
//                // 城市定价
//                itemQuery.setCityId(cityId);
//                itemToList = productTariffItemCityPriceService.listItemPriceByQuery(itemQuery);
//            } else {
//                // 系数定价
//                itemToList = productTariffGroupItemService.listItemPriceByQuery(itemQuery);
//            }
//            log.info("项目itemToList:{}", itemToList);
//
//            PriceCalDTO calDTO = new PriceCalDTO(channelId, cityId, productItem.getBrandId(), bizType, null);
//
//            for (ItemTo itemTo : itemToList) {
//                // 设置定价方式(计算价格前需设置定价方式)
//                itemTo.setTariffName(tariff.getTariffName());
//                itemTo.setTariffType(tariff.getTariffType());
//                itemTo.setPriceType(tariff.getPriceType());
//
//                // 计算单价
//                commonBService.calPriceDetail(itemTo, calDTO);
//                log.info("项目itemTo计算价格后数据:{}", itemTo);
//
//                itemTo.setProductName(product.getName());
//                itemTo.setDesc(productTariffVO.getDesc());
//                itemTo.setSpecialDesc(productTariffVO.getSpecialDesc());
//
//                // 查询项目分组
//                ServiceGroup group = serviceGroupService.findByKey(itemTo.getGroupId());
//                itemTo.setGroupName(group.getGroupName());
//                itemTo.setGroupSort(group.getSort());
//            }
//            dros.addAll(itemToList);
//        }
//        return dros;
//    }

    @Override
    @Cacheable(cacheNames = "redis5m", key = "'price:listCheckTariff:AdvanceFtProductCheckTariffQuery:'+#p0", unless = "#result == null")
    public Map<Integer, Boolean> listCheckTariff(AdvanceFtProductCheckTariffQuery query) {

        Integer channelId = query.getChannelId();
        Integer cityId = query.getCityId();
        Integer bizType = query.getBizType();
        Integer showType = query.getShowType();
        Map<Integer, Boolean> dros = new HashMap<>(query.getProductIdList().size());
        for (Integer productId : query.getProductIdList()) {
            // 查询产品
            ServProduct product = servProductService.findByKeyWithCache(productId);
            if (Objects.isNull(product)) {
                log.error("产品不存在，id{}", productId);
                continue;
            }
            if (NumberUtil.isNullOrZero(showType)) {
                showType = product.getShowType();
            }
            Integer servCategId = product.getServCategId();
            Integer categId = product.getCategId();

            // 如果是后端产品，转换成前端产品分类
            if (Objects.equals(showType, ProductConsts.ERP_PRODUCT_TYPE)) {
                List<ShowCategoryAssociationVO> showCategoryAssociationVOS =
                        showCategoryAssociationBService.listByCategoryId(product.getServCategId(), product.getCategOneId(), product.getCategId());
                if (!CollectionUtils.isEmpty(showCategoryAssociationVOS)) {
                    servCategId = showCategoryAssociationVOS.get(0).getShowServCategId();
                    categId = showCategoryAssociationVOS.get(0).getShowCategId();
                }
            }

            // 计价器试点
            Boolean pilotFlagTa = channelPriceBService.checkByChannelIdAndCityIdAndTypeAndCateg(channelId, cityId, OnePriceConsts.TARIFF, servCategId, categId);
            if (!pilotFlagTa) {
                dros.put(productId, false);
                continue;
            }
            // 查询计价器价格
            Map<Integer, Integer> traiffMap = commonBService.getTariff(channelId, Arrays.asList(productId), showType, bizType, ProductDict.TRIFF_TYPE_TARIFF);
            if (!CollectionUtils.isEmpty(traiffMap)) {
                dros.put(productId, true);
                continue;
            }

            // 提前付试点
            Boolean pilotFlagAd = channelPriceBService.checkByChannelIdAndCityIdAndTypeAndCateg(channelId, cityId, PilotConfigEnum.PAY_ADVANCE.getType(), servCategId, categId);
            if (!pilotFlagAd) {
                dros.put(productId, false);
                continue;
            }
            // 查询提前付价格
            Map<Integer, Integer> advanceMap = commonBService.getTariff(channelId, Arrays.asList(productId), showType, bizType, ProductDict.TRIFF_TYPE_ADVANCE);
            if (!CollectionUtils.isEmpty(advanceMap)) {
                dros.put(productId, true);
                continue;
            }
            dros.put(productId, false);
        }
        return dros;
    }

    @Override
    @Cacheable(cacheNames = "redis5m", key = "'price:listCheckAdvance:AdvanceFtProductCheckTariffQuery:'+#p0", unless = "#result == null")
    public Map<Integer, Boolean> listCheckAdvance(AdvanceFtProductCheckTariffQuery query) {

        Integer channelId = query.getChannelId();
        Integer cityId = query.getCityId();
        Integer bizType = query.getBizType();
        Integer showType = query.getShowType();
        Map<Integer, Boolean> dros = new HashMap<>(query.getProductIdList().size());
        for (Integer productId : query.getProductIdList()) {
            // 查询产品
            ServProduct product = servProductService.findByKeyWithCache(productId);
            if (Objects.isNull(product)) {
                log.error("产品不存在，id{}", productId);
                continue;
            }
            if (NumberUtil.isNullOrZero(showType)) {
                showType = product.getShowType();
            }
            Integer servCategId = product.getServCategId();
            Integer categId = product.getCategId();

            // 如果是后端产品，转换成前端产品分类
            if (Objects.equals(showType, ProductConsts.ERP_PRODUCT_TYPE)) {
                List<ShowCategoryAssociationVO> showCategoryAssociationVOS =
                        showCategoryAssociationBService.listByCategoryId(product.getServCategId(), product.getCategOneId(), product.getCategId());
                if (!CollectionUtils.isEmpty(showCategoryAssociationVOS)) {
                    servCategId = showCategoryAssociationVOS.get(0).getShowServCategId();
                    categId = showCategoryAssociationVOS.get(0).getShowCategId();
                }
            }

            // 计价器试点
            Boolean pilotFlagTa = channelPriceBService.checkByChannelIdAndCityIdAndTypeAndCateg(channelId, cityId, OnePriceConsts.TARIFF, servCategId, categId);
            if (!pilotFlagTa) {
                dros.put(productId, false);
                continue;
            }

            // 提前付试点
            Boolean pilotFlagAd = channelPriceBService.checkByChannelIdAndCityIdAndTypeAndCateg(channelId, cityId, PilotConfigEnum.PAY_ADVANCE.getType(), servCategId, categId);
            if (!pilotFlagAd) {
                dros.put(productId, false);
                continue;
            }
            // 查询提前付价格
            Map<Integer, Integer> advanceMap = commonBService.getTariff(channelId, Arrays.asList(productId), showType, bizType, ProductDict.TRIFF_TYPE_ADVANCE);
            if (!CollectionUtils.isEmpty(advanceMap)) {
                dros.put(productId, true);
                continue;
            }
            dros.put(productId, false);
        }
        return dros;
    }

}
